import { MachineCoordinator } from "@/Battle/StateMechine/MachineCoordinator.js";
import CombatEventBus from "@/Battle/CombatEventBus.js";

import { BattleInput } from "@/Battle/Input/BattleInput.js";
import { AutoInput } from "@/Battle/Input/AutoInput.js";
import { ActionTransition } from "@/Battle/ActionTransition/ActionTransition.js";
import { ActionApply } from "@/Battle/ActionApply/ActionApply.js";

export class BattleManager{
    static mechine=new MachineCoordinator();
    /**
     * @type {{[key:string]:BattleInput|AutoInput|ActionTransition}}
     */
    static instrusions={};

    static current_battlers_queue=[];
    static current_battler_index=-1;
    static next_battlers_queue=[];

    static startBattle(){
        $gameSystem.onBattleStart();
        $gameParty.onBattleStart();
        $gameTroop.onBattleStart();
        this.current_battlers_queue=$gameParty.members().concat($gameTroop.members());
        this.current_battlers_queue.sort((a,b)=>a.agi-b.agi);

        this.mechine.start();
        this.addInstrusion('input',new BattleInput());
        this.addInstrusion('autoInput',new AutoInput());
        this.addInstrusion('transition',new ActionTransition());
        this.addInstrusion('actionapply',new ActionApply());
    }

    static update(){
        this.mechine.update();
        CombatEventBus.processEvents();
    }

    static destroy(){
        this.mechine.clear();
        this.unloadInstrusions();
        this.current_battlers_queue.length=0;;
        this.current_battler_index=-1;
        this.next_battlers_queue.length=0;
    }

    static addInstrusion(name,instrusion){
        if(this.instrusions[name]){
            this.instrusions[name].unload();
        }
        instrusion.load();
        this.instrusions[name]=instrusion;
    }

    static onInstrusion(name,eventName,cb){
        this.instrusions[name]?.on(eventName,cb);
    }

    static unloadInstrusions(){
        for(let key in this.instrusions){
            this.instrusions[key].unload();
        }
        this.instrusions={};
    }

    static peekNextBattler(){
        return this.current_battlers_queue[this.current_battler_index+1];
    }

    static peekCurrentBattler(){
        return this.current_battlers_queue[this.current_battler_index];
    }
    static getNextBattler(){
        return this.current_battlers_queue[++this.current_battler_index];
    }

    static unshiftBattler(battler){
        if(this.current_battler_index==-1){
            this.current_battlers_queue.unshift(battler);
        }else{
            this.current_battlers_queue.splice(this.current_battler_index,0,battler);
        }
    }

    static releaseBattler(battle){
        if(!battle)return;
        this.next_battlers_queue.push(battle);
    }

    static peekCurrentAction(){
        return this.current_battlers_queue[this.current_battler_index]?.action(0);
    }

    static getNextAction(){
        return this.current_battlers_queue[this.current_battler_index]?.shiftAction();
    }

    static canEscape(){
        return true;
    }
}